package base

import (
	"blot/structural"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"strings"
)

type HTTPClient struct {
	client  *http.Client
	headers []structural.Headers
	url     string
	method  string
	host    string
}

func redrect(req *http.Request, via []*http.Request) error {
	return http.ErrUseLastResponse
}
func NewHTTPClient(setting structural.Setting) *HTTPClient {
	//初始化client以及数据
	var clients HTTPClient
	clients.client = &http.Client{
		Timeout:       setting.Timeout,
		CheckRedirect: redrect, //禁止自动重定向
	}
	clients.method = setting.Method
	clients.headers = setting.Header
	clients.host = setting.Host
	if clients.method == "" {
		clients.method = http.MethodGet
	}
	return &clients
}
func (client *HTTPClient) Initialize(url string, body structural.Body) (resp *http.Response, err error) {
	//request初始化

	req, _ := http.NewRequest(client.method, url, body.Data)
	req.Header.Set("User-Agent", fmt.Sprintf("%s", structural.Useraget))
	req.Header.Set("Accept", "*/*")
	if len(client.headers) > 0 {

		for _, header := range client.headers {

			req.Header.Set(header.Key, header.Value)
		}
	}
	if resp, err = client.client.Do(req); err != nil {
		return nil, err
	}
	return

}

func (client *HTTPClient) Request(url string, body structural.Body) ([]byte, int, http.Header, error) {
	//请求

	resp, err := client.Initialize(url, body)
	if err != nil {
		return nil, 0, nil, err
	}
	defer func() {
		resp.Body.Close()
	}()
	resp_data, _ := io.ReadAll(resp.Body)

	return resp_data, resp.StatusCode, resp.Header, nil

}

func (client *HTTPClient) RequestScan(url string, body structural.Body) Scan {
	var text Scan
	resp, err := client.Initialize(url, body)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	text.Text = data
	return text

}
func UrlDispose(url string) (Url, domname string, err error) {
	//处理输入的url

	if url == "" {

		return "", "", errors.New("解析url错误，请确保带有url")
	}
	domain := strings.Split(url, "/")
	Url = domain[0] + "//" + domain[2]
	domname = domain[2]

	return

}

type Scan struct {
	Text []byte
}

func (DataScan Scan) Scan(value any) {

	dataType := reflect.TypeOf(value)
	if dataType.Kind() == reflect.Ptr { //通过kind函数获取到是否为指针
		dataValue := reflect.ValueOf(value).Elem()
		switch dataType.Elem().Kind() { //获取传入变量的类型种类
		case reflect.String:
			dataValue.SetString(string(DataScan.Text))
		case reflect.Struct:
			for i := 0; i < dataType.Elem().NumField(); i++ { //通过反射对结构体赋值
				name := DataScan.jsonAssert()[strings.ToLower(dataType.Elem().Field(i).Name)] //结构体名称转小写
				if dataValue.Type() == reflect.TypeOf(name) {
					dataValue.FieldByName(dataType.Elem().Field(i).Name).Set(reflect.ValueOf(name))
				} else {
					panic("类型不匹配")
				}
			}
		}
	} else {
		panic("传入类型需要指针")
	}

}

func (Data Scan) jsonAssert() map[any]any {
	//判断是否为json
	var mapD map[any]any
	if err := json.Unmarshal(Data.Text, &mapD); err != nil {
		panic("返回数据非json")
	}
	return mapD
}

func jsonData(json_data map[string]any) string {
	//map转换成json数据
	data, err := json.Marshal(json_data)
	if err != nil {
		panic(err)
	}
	return string(data)
}
